using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;

namespace Woz
{
    public partial class TransitionPanel : UserControl
    {
        /// <summary>
        /// static constructor initializes static variables
        /// </summary>
        static TransitionPanel()
        {
            // initialize the move icon image
            Woz.TransitionPanel.sMoveIconImage = global::Woz.Properties.resources.icon_move_screen_thumbnail;
        }

        /// <summary>
        /// default constructor
        /// </summary>
        public TransitionPanel()
        {
            InitializeComponent();

            // enable double buffering
            this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                ControlStyles.UserPaint |
                ControlStyles.ResizeRedraw |
                ControlStyles.OptimizedDoubleBuffer,
                true);

            // create the list of move icons
            this.mMoveIcons = new List<PictureBox>();

            // a thirty percent semitransparent color matrix
            ColorMatrix colorMatrix = new ColorMatrix(new float[5][] {
                    new float[5]{1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
                    new float[5]{0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
                    new float[5]{0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
                    new float[5]{0.0f, 0.0f, 0.0f, 0.3f, 0.0f},
                    new float[5]{0.0f, 0.0f, 0.0f, 0.0f, 1.0f} });

            // initialize the image attributes
            this.mSemiTransparentImageAttributes = new ImageAttributes();
            this.mSemiTransparentImageAttributes.SetColorMatrix(colorMatrix);

            // initalize the members needed for drawing the semi transparent screen thumbnail
            this.mRectangleOfSemiTransparentScreenThumbnail = new Rectangle(Point.Empty, Woz.ScreenThumbnail.ScreenThumbnailSize);
            this.mSemiTransparentImageOfScreenThumbnail = new Bitmap(Woz.ScreenThumbnail.ScreenThumbnailSize.Width, Woz.ScreenThumbnail.ScreenThumbnailSize.Height);

            // intialize the transition final rectangle
            this.mCurrentTransitionDest = Rectangle.Empty;
        }

        /// <summary>
        /// gets and sets the flag representing whether or not to draw the semi transparent screenthumbnail
        /// </summary>
        public bool DrawSemiTransparentScreenThumbnail
        {
            get
            {
                return this.mDrawSemiTransparentScreenThumbnail;
            }

            set
            {
                // elimate redundant calls of this function
                if (this.mDrawSemiTransparentScreenThumbnail == value)
                {
                    return;
                }

                // set the value on our flag
                this.mDrawSemiTransparentScreenThumbnail = value;

                // check if were now drawing
                if (this.mDrawSemiTransparentScreenThumbnail)
                {
                    // we are now drawing so set this flag so we know that this is the first time happening
                    this.mSemiTransparentThumbnailHasEnteredBefore = false;
                }
            }
        }

        /// <summary>
        /// gets or sets the bitmap of the semi transparent screenthumbnail to draw
        /// </summary>
        public Bitmap SemiTransparentImageOfScreenThumbnail
        {
            get
            {
                return this.mSemiTransparentImageOfScreenThumbnail;
            }

            set
            {
                this.mSemiTransparentImageOfScreenThumbnail = value;
            }
        }

        /// <summary>
        /// set the point for the mouse location when drawing the semi transparent screenthumbnail
        /// </summary>
        public Point MousePositionForSemiTransparentScreenThumbnail
        {
            set
            {
                // calculate the proper position of the rectangle
                this.mRectangleOfSemiTransparentScreenThumbnail.Location = new Point(value.X - (Woz.ScreenThumbnail.ScreenThumbnailSize.Width / 2), value.Y - (Woz.ScreenThumbnail.ScreenThumbnailSize.Height / 2));
            }
        }

        /// <summary>
        /// resets this transition panel
        /// </summary>
        public void Reset()
        {
            // clear child controls
            this.Controls.Clear();

            // clear selected and mouse over transitions
            this.mMouseOverTransitionArrow = null;
            this.mSelectedTransitionArrow = null;
            this.mCurrentTransitionDest = Rectangle.Empty;
        }

        /// <summary>
        /// adds the passed in screenthumbnail to ourselves
        /// </summary>
        /// <param name="pScreenThumbnail">screenthumbnail to add</param>
        /// <param name="pHasBeenMoved">indicates whether this was moved here by drag and drop</param>
        public void AddScreenThumbnail(Woz.ScreenThumbnail pScreenThumbnail, bool pHasBeenMoved)
        {          
            // set its position
            if (pHasBeenMoved)
            {
                pScreenThumbnail.Location = this.mRectangleOfSemiTransparentScreenThumbnail.Location;
            }
            
            // create a new move icon for this thumbnail
            PictureBox moveIcon = new PictureBox();
            moveIcon.Size = Woz.TransitionPanel.sMoveIconImage.Size;
            moveIcon.Location = new Point(pScreenThumbnail.Left + (pScreenThumbnail.Width / 2) - (moveIcon.Width / 2), pScreenThumbnail.Top - (moveIcon.Height / 2));
            moveIcon.Tag = pScreenThumbnail;
            moveIcon.Image = Woz.TransitionPanel.sMoveIconImage;
            
            // add some callbacks to this move icon
            moveIcon.MouseDown += new MouseEventHandler(this.cMoveIconMouseDown);
            moveIcon.MouseUp += new MouseEventHandler(this.cMoveIconMouseUp);
            moveIcon.MouseMove += new MouseEventHandler(this.cMoveIconMouseMove);
            moveIcon.MouseEnter += new EventHandler(this.cMoveIconMouseEnter);
            moveIcon.MouseLeave += new EventHandler(this.cMoveIconMouseLeave);

            // set this flag for the first thumbnail
            pScreenThumbnail.TabIndex = (this.Controls.Count == 0) ? 1 : 0;
            pScreenThumbnail.Tag = "In-Use";

            // finally add this move icon to oursevles
            this.Controls.Add(moveIcon);

            // then add it to our list
            this.Controls.Add(pScreenThumbnail);

            // make these controls show up in front of the existing ones
            pScreenThumbnail.BringToFront();
            moveIcon.BringToFront();
        }

        private void cMoveIconMouseEnter(object pSender, EventArgs pEventArgs)
        {
            // tell the screen thumbnail of this move icon to highlight
            Woz.ScreenThumbnail screenThumbnail = ((Woz.ScreenThumbnail)((PictureBox)pSender).Tag);
            screenThumbnail.Highlighted = true;
        }

        private void cMoveIconMouseLeave(object pSender, EventArgs pEventArgs)
        {
            // tell the screen thumbnail of this move icon to unhighlight
            Woz.ScreenThumbnail screenThumbnail = ((Woz.ScreenThumbnail)((PictureBox)pSender).Tag);
            screenThumbnail.Highlighted = false;
        }

        /// <summary>
        /// our own version of the paint that handles the semi transparent drawing when needed
        /// </summary>
        /// <param name="pEventArgs">paint event args</param>
        protected override void OnPaint(PaintEventArgs pEventArgs)
        {
            // save a reference to the graphics
            Graphics graphics = pEventArgs.Graphics;

            // check if were suppose to be drawing the semi transparent screenthumbnail
            if (this.mDrawSemiTransparentScreenThumbnail)
            {
                // check if this is not the first time were doing this
                if (!this.mSemiTransparentThumbnailHasEnteredBefore)
                {
                    // first clear the area were drawing to
                    graphics.SetClip(Rectangle.Union(this.mPreviousRectangleOfSemiTransparentScreenThumbnail, this.mRectangleOfSemiTransparentScreenThumbnail));
                    graphics.Clear(this.BackColor);

                    // set this flag so we dont come in here again
                    this.mSemiTransparentThumbnailHasEnteredBefore = true;
                }
                
                // draw the semi transparent image of the screenthumbnail
                graphics.DrawImage(this.mSemiTransparentImageOfScreenThumbnail, this.mRectangleOfSemiTransparentScreenThumbnail, 0, 0, Woz.ScreenThumbnail.ScreenThumbnailSize.Width, Woz.ScreenThumbnail.ScreenThumbnailSize.Height, GraphicsUnit.Pixel, this.mSemiTransparentImageAttributes);

                // save the previous rectangle
                this.mPreviousRectangleOfSemiTransparentScreenThumbnail = this.mRectangleOfSemiTransparentScreenThumbnail;
            }

            // or check if were doing drawing the doesnt involve the semi transparent screenthumbnail
            else
            {
                // set the clipping area
                if (!pEventArgs.ClipRectangle.IsEmpty)
                {
                    graphics.SetClip(pEventArgs.ClipRectangle);
                }

                // clear the background color and smoothen out the graphics
                graphics.Clear(this.BackColor);
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                // check to see if we are in the process of drawing a transition arrow
                if (this.mCurrentTransitionDest != Rectangle.Empty)
                {
                    Woz.TransitionArrow.DrawTransition(graphics, 
                        this.mStartingScreenThumbnail.Bounds, 
                        this.mCurrentTransitionDest);
                }
            }

            // go through all of the transition arrows and draw them one by one
            graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            foreach (Woz.TransitionArrow transition in Woz.ScreenManager.Instance.TransitionArrows)
            {
                transition.Draw(graphics);
            }
        }


        protected override void OnMouseDown(MouseEventArgs pMouseEventArgs)
        {
            // the rectangle to invalidate
            Rectangle invalidateRect = Rectangle.Empty;

            // deselect the selected 
            if (this.mSelectedTransitionArrow != null)
            {
                invalidateRect = this.mSelectedTransitionArrow.BoundingBox;
                this.mSelectedTransitionArrow.Deselect();
                this.mSelectedTransitionArrow = null;
                Woz.InterfaceManager.Instance.Buttons["Delete"].Enabled = false;
            }

            // select a new transition line
            foreach (Woz.TransitionArrow transition in Woz.ScreenManager.Instance.TransitionArrows)
            {
                if (transition.HitTest(pMouseEventArgs.Location))
                {
                    this.mSelectedTransitionArrow = transition;
                    transition.Select();
                    Woz.InterfaceManager.Instance.Buttons["Delete"].Enabled = true;

                    if (invalidateRect != Rectangle.Empty)
                    {
                        invalidateRect = Rectangle.Union(invalidateRect, transition.BoundingBox);
                    }
                    else
                    {
                        invalidateRect = transition.BoundingBox;
                    }
                    break;
                }
            }

            if (invalidateRect != Rectangle.Empty)
            {
                this.Invalidate(invalidateRect);
            }
            base.OnMouseDown(pMouseEventArgs);
        }

        protected override void OnMouseUp(MouseEventArgs pMouseEventArgs)
        {
            if (this.mSelectedTransitionArrow != null)
            {
                if (this.mSelectedTransitionArrow.StretchedTooFar)
                {
                    Woz.ScreenManager.Instance.RemoveScreenTransition(this.mSelectedTransitionArrow);
                }
            }
            
            // make sure to invalidate the canvas
            if (this.mCurrentTransitionDest != Rectangle.Empty)
            {
                this.Invalidate();
                this.mCurrentTransitionDest = Rectangle.Empty;
            }

            base.OnMouseUp(pMouseEventArgs);
        }

        protected override void OnMouseMove(MouseEventArgs pMouseEventArgs)
        {
            Rectangle invalidateRect = Rectangle.Empty;
            if (pMouseEventArgs.Button == MouseButtons.Left)
            {
                if (this.mSelectedTransitionArrow != null)
                {
                    invalidateRect = this.mSelectedTransitionArrow.BoundingBox;
                    this.mSelectedTransitionArrow.StrecthTo(pMouseEventArgs.Location);
                    base.Invalidate(Rectangle.Union(this.mSelectedTransitionArrow.BoundingBox, invalidateRect));
                }
            }
            else
            {
                if (this.mMouseOverTransitionArrow != null)
                {
                    invalidateRect = this.mMouseOverTransitionArrow.BoundingBox;
                    this.mMouseOverTransitionArrow.MouseOver = false;
                }

                foreach (Woz.TransitionArrow transition in Woz.ScreenManager.Instance.TransitionArrows)
                {
                    if (transition.HitTest(pMouseEventArgs.Location))
                    {
                        if (this.mMouseOverTransitionArrow != null)
                        {
                            if (invalidateRect != Rectangle.Empty)
                            {
                                invalidateRect = Rectangle.Union(invalidateRect, this.mMouseOverTransitionArrow.BoundingBox);
                            }
                            else
                            {
                                invalidateRect = this.mMouseOverTransitionArrow.BoundingBox;
                            }
                            this.mMouseOverTransitionArrow.MouseOver = false;
                        }
                        transition.MouseOver = true;
                        this.mMouseOverTransitionArrow = transition;
                        break;
                    }
                }

                if (this.mMouseOverTransitionArrow != null)
                {
                    if (invalidateRect != Rectangle.Empty)
                    {
                        invalidateRect = Rectangle.Union(invalidateRect, this.mMouseOverTransitionArrow.BoundingBox);
                    }
                    else
                    {
                        invalidateRect = this.mMouseOverTransitionArrow.BoundingBox;
                    }
                    base.Invalidate(invalidateRect);
                }
            }
            base.OnMouseMove(pMouseEventArgs);
        }

        internal void EnterTransitionPanel()
        {
            // might want to enable
            Woz.InterfaceManager.Instance.Buttons["Delete"].Enabled = (this.mSelectedTransitionArrow != null);

            // subscribe to the delete event
            Woz.InterfaceManager.Instance.Buttons["Delete"].Click += this.cDeleteButtonClicked;
        }

        internal void LeaveTransitionPanel()
        {
            // clear it first
            Woz.InterfaceManager.Instance.Buttons["Delete"].Enabled = false;

            // unsubscribe to the delete event
            Woz.InterfaceManager.Instance.Buttons["Delete"].Click -= this.cDeleteButtonClicked;
        }

        /// <summary>
        /// gets called when there is a mouse down on an arbitrary move icon
        /// </summary>
        /// <param name="pSender">the move icon that fired the event</param>
        /// <param name="pEventArgs">mouse event args</param>
        private void cMoveIconMouseDown(object pSender, MouseEventArgs pEventArgs)
        {
            this.mMovingScreenThumbnail = true;
            this.mMouseDownPositionInMoveIcon = pEventArgs.Location;

            // deselect the selected 
            if (this.mSelectedTransitionArrow != null)
            {
                this.mSelectedTransitionArrow.Deselect();
                this.mSelectedTransitionArrow = null;
                Woz.InterfaceManager.Instance.Buttons["Delete"].Enabled = false;
            }
        }

        /// <summary>
        /// gets called when there is a mouse up on an arbitrary move icon
        /// </summary>
        /// <param name="pSender">the move icon that fired the event</param>
        /// <param name="pEventArgs">mouse event args</param>
        private void cMoveIconMouseUp(object pSender, MouseEventArgs pEventArgs)
        {
            this.mMovingScreenThumbnail = false;
        }

        /// <summary>
        /// gets called when there is a mouse move on an arbitrary move icon
        /// </summary>
        /// <param name="pSender">the move icon that fired the event</param>
        /// <param name="pEventArgs">mouse event args</param>
        private void cMoveIconMouseMove(object pSender, MouseEventArgs pEventArgs)
        {
            // make sure were actually dragging thing
            if (!this.mMovingScreenThumbnail)
            {
                return;
            }

            // if we made it this far then we are indeed dragging a move icon

            // save the move icon and screen thumbnail
            Control moveIcon = (Control)pSender;
            Control screenThumbnail = ((Control)moveIcon.Tag);

            // create a point for the new position
            Point newPosition = Point.Empty;

            // calculate the new position of the move icon
            newPosition.X = moveIcon.Left + pEventArgs.X - this.mMouseDownPositionInMoveIcon.X;
            newPosition.Y = moveIcon.Top + pEventArgs.Y - this.mMouseDownPositionInMoveIcon.Y;

            // calculate the halves of the screen thumbnail and the move icon
            int halfScreenThumbnailWidth = screenThumbnail.Width / 2;
            int halfMoveIconWidth = moveIcon.Width / 2;

            // make sure the actual screenthumbnail stays bounded
            if (newPosition.Y < 0)
            {
                newPosition.Y = 0;
            }

            if (newPosition.X < halfScreenThumbnailWidth - halfMoveIconWidth)
            {
                newPosition.X = halfScreenThumbnailWidth - halfMoveIconWidth;
            }

            // now move the move icon
            moveIcon.Location = newPosition;

            // and move its corresponding screen thumbnail
            newPosition.X += halfMoveIconWidth - halfScreenThumbnailWidth;
            newPosition.Y += moveIcon.Height / 2;
            screenThumbnail.Location = newPosition;
        }

        /// <summary>
        /// checks to see if the given location is inside of a transition screen thumbnail
        /// </summary>
        /// <param name="pLocation">the location to check for</param>
        /// <returns>the screen thumbnail the location is over or null if none</returns>
        private Woz.ScreenThumbnail HitTest(Point pLocation)
        {
            foreach (Woz.Screen screen in Woz.ScreenManager.Instance.Screens)
            {
                if (screen.TransitionsThumbnail.Bounds.Contains(pLocation))
                {
                    return screen.TransitionsThumbnail;
                }
            }

            return null;
        }

        private Point FindParentLocation(Control pChild, Point pLocation)
        {
            while (pChild != null)
            {
                if (pChild == this)
                {
                    return pLocation;
                }
                pLocation.X += pChild.Left;
                pLocation.Y += pChild.Top;
                pChild = pChild.Parent;
            }
            return Point.Empty;
        }

        internal void cScreenThumbnailMouseUp(object pSender, MouseEventArgs pMouseEventArgs)
        {            
            // find the final screen thumbnail
            Rectangle invalidateRect = Rectangle.Empty;
            Point absolutePosition = this.FindParentLocation(pSender as Control, pMouseEventArgs.Location);

            // calculate the invalidate rectangle
            if (this.mCurrentTransitionDest != Rectangle.Empty)
            {
                if (this.mStartingScreenThumbnail != null)
                {
                    invalidateRect = Rectangle.Union(this.mStartingScreenThumbnail.Bounds, this.mCurrentTransitionDest);
                }
                else
                {
                    invalidateRect = this.mCurrentTransitionDest;
                }
                invalidateRect.Inflate(10, 25);
            }
            
            // check if we have a new ending screen thumbnail
            if (this.mEndingScreenThumbnail != null)
            {
                // now add the transition between the start and end screens
                Woz.ScreenManager.Instance.AddScreenTransition(this.mStartingScreenThumbnail, this.mEndingScreenThumbnail);

                // tell this ending screen thumbnail to unhighlight
                this.mEndingScreenThumbnail.Highlighted = false;
            }

            // clear the starting and ending nodes
            this.mStartingScreenThumbnail = null;
            this.mEndingScreenThumbnail = null;

            // clear the transition dest rectangle
            this.mCurrentTransitionDest = Rectangle.Empty;

            // invalidate the invalidate rectangle if its not empty
            if (invalidateRect != Rectangle.Empty)
            {
                this.Invalidate(invalidateRect);
            }
        }

        internal void cScreenThumbnailMouseMove(object pSender, MouseEventArgs pMouseEventArgs)
        {
            if (pMouseEventArgs.Button != MouseButtons.Left)
            {
                return;
            }
            if (this.mStartingScreenThumbnail == null)
            {
                return;
            }

            Point absolutePosition = this.FindParentLocation(pSender as Control, pMouseEventArgs.Location);
            Rectangle invalidateRect = Rectangle.Union(this.mCurrentTransitionDest, this.mStartingScreenThumbnail.Bounds);
            invalidateRect.Inflate(10, 25);

            // check which screen thumbnail has the mouse over it
            Woz.ScreenThumbnail mouseOveredScreenThumbnail = this.HitTest(absolutePosition);

            // ignore this screen thumbnail if it is the starting thumbnail
            if (mouseOveredScreenThumbnail == this.mStartingScreenThumbnail)
            {
                return;
            }

            // check if we found nothing
            if (mouseOveredScreenThumbnail == null)
            {
                // check if we used to have something
                if (this.mEndingScreenThumbnail != null)
                {
                    // this thumbnail use to be the ending one but isnt anymore so unhighlight it
                    this.mEndingScreenThumbnail.Highlighted = false;

                    // we no longer have an ending thumbnail
                    this.mEndingScreenThumbnail = null;
                }

                // just draw the transition with no snapping
                this.mCurrentTransitionDest = Rectangle.FromLTRB(absolutePosition.X, absolutePosition.Y, absolutePosition.X + 1, absolutePosition.Y + 1);
            }

            // or check if we indeed found something
            else
            {
                // check if this is different than something weve already found
                if (mouseOveredScreenThumbnail != this.mEndingScreenThumbnail)
                {
                    // this is different so first unhighlight our current one
                    if (this.mEndingScreenThumbnail != null)
                    {
                        // unhighlight our former ending screen
                        this.mEndingScreenThumbnail.Highlighted = false;

                        // for now we no longer have an ending thumbnail
                        this.mEndingScreenThumbnail = null;
                    }

                    // flag whether or not the user is trying to draw an existing transition
                    bool transitionExists = false;

                    // loop through all the transitions
                    foreach (Woz.TransitionArrow  transition in Woz.ScreenManager.Instance.TransitionArrows)
                    {
                        // check if this transition is the same as the one the user is trying to draw
                        if ((transition.StartThumbnail == this.mStartingScreenThumbnail) && (transition.EndThumbnail == mouseOveredScreenThumbnail))
                        {
                            // it is the same so set the flag
                            transitionExists = true;

                            // leave the loop
                            break;
                        }
                    }

                    // check if this is an existing transition 
                    if (transitionExists)
                    {
                        // just draw the arrow with no snapping
                        this.mCurrentTransitionDest = Rectangle.FromLTRB(absolutePosition.X, absolutePosition.Y, absolutePosition.X + 1, absolutePosition.Y + 1);
                    }

                    else
                    {
                        // it is so set this newly found one our ending one
                        this.mEndingScreenThumbnail = mouseOveredScreenThumbnail;

                        // tell it to highlight
                        this.mEndingScreenThumbnail.Highlighted = true;

                        // draw the transition arrow snapped to this bad boy
                        this.mCurrentTransitionDest = this.mEndingScreenThumbnail.Bounds;
                    }
                }
            }

            // invalidate the rectangle
            this.Invalidate(invalidateRect);
        }

        Woz.ScreenThumbnail mEndingScreenThumbnail;
        //Woz.ScreenThumbnail mMouseOveredScreenThumbnail;

        internal void cScreenThumbnailMouseDown(object pSender, MouseEventArgs pMouseEventArgs)
        {
            this.mStartingScreenThumbnail = pSender as ScreenThumbnail;

            // deselect the selected 
            if (this.mSelectedTransitionArrow != null)
            {
                this.mSelectedTransitionArrow.Deselect();
                this.mSelectedTransitionArrow = null;
                Woz.InterfaceManager.Instance.Buttons["Delete"].Enabled = false;
            }
        }

        internal void cScreenThumbnailDoubleClick(object pSender, EventArgs pEventArgs)
        {
            Woz.ScreenThumbnail thumbnail = pSender as Woz.ScreenThumbnail;
            if (thumbnail != null)
            {
                Woz.ScreenManager.Instance.SelectedScreen = thumbnail.Screen;
                Woz.MainForm.Instance.SwitchMode(Woz.StaticVariables.Instance.DesignScreens);
            }
        }

        private void cDeleteButtonClicked(Woz.Button pButton)
        {
            if (pButton != null)
            {
                if (this.mSelectedTransitionArrow != null)
                {
                    this.mSelectedTransitionArrow.Deselect();
                    Woz.ScreenManager.Instance.RemoveScreenTransition(this.mSelectedTransitionArrow);
                    this.mSelectedTransitionArrow = null;
                    Woz.InterfaceManager.Instance.Buttons["Delete"].Enabled = false;
                }
            }
        }
        
        /// <summary>
        /// image to be used for the move icon
        /// </summary>
        private static Bitmap sMoveIconImage;

        /// <summary>
        /// flag whether or not to draw the semi transparent image of the screenthumbnail
        /// </summary>
        private bool mDrawSemiTransparentScreenThumbnail;

        /// <summary>
        /// destination rectangle of the semi transparent image of the screenthumbnail
        /// </summary>
        private Rectangle mRectangleOfSemiTransparentScreenThumbnail;
        
        /// <summary>
        /// previous destination rectangle of the semi transparent image of the screenthumbnail
        /// </summary>
        private Rectangle mPreviousRectangleOfSemiTransparentScreenThumbnail;
        
        /// <summary>
        /// semi transparent image of the screenthumbnail
        /// </summary>
        private Bitmap mSemiTransparentImageOfScreenThumbnail;

        /// <summary>
        /// attributes used to to the semi transparency
        /// </summary>
        private ImageAttributes mSemiTransparentImageAttributes;

        /// <summary>
        /// list of move icons which are created for every screenthumbnail that is added
        /// </summary>
        private List<PictureBox> mMoveIcons;

        /// <summary>
        /// starting screen thumbnail to start drawing a transition from
        /// </summary>
        private Woz.ScreenThumbnail mStartingScreenThumbnail;

        /// <summary>
        /// the current transition destination box
        /// </summary>
        private Rectangle mCurrentTransitionDest;

        /// <summary>
        /// the selected transition arrow
        /// </summary>
        private TransitionArrow mSelectedTransitionArrow;

        /// <summary>
        /// the transition arrow that the mouse is over
        /// </summary>
        private TransitionArrow mMouseOverTransitionArrow;

        /// <summary>
        /// position of the mouse down within the move icon
        /// </summary>
        private Point mMouseDownPositionInMoveIcon;

        /// <summary>
        /// flag whether or not a screenthumbnail is being moved
        /// </summary>
        private bool mMovingScreenThumbnail;

        private bool mSemiTransparentThumbnailHasEnteredBefore;
    }
}
